package com.denlaku.longan.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import java.util.List;
import java.util.concurrent.RecursiveAction;

/**
 * Applier Action
 *
 * @author tianx
 */
@Slf4j
public class ForkJoinRunnableAction extends RecursiveAction {
    private final List<Runnable> tasks;
    private final boolean throwException;

    public ForkJoinRunnableAction(List<Runnable> tasks, boolean throwException) {
        this.tasks = tasks;
        this.throwException = throwException;
    }

    private ForkJoinRunnableAction of(Runnable task) {
        return new ForkJoinRunnableAction(Lists.of(task), throwException);
    }

    @Override
    protected void compute() {
        if (CollectionUtils.isEmpty(tasks)) {
            return;
        }
        if (tasks.size() == 1) {
            doCompute(tasks.get(0));
        } else {
            List<ForkJoinRunnableAction> actions = Lists.toList(tasks, this::of);
            invokeAll(actions);
            actions.forEach(ForkJoinRunnableAction::join);
        }
    }

    private void doCompute(Runnable task) {
        try {
            task.run();
        } catch (Exception e) {
            log.error("Failed to invoke apply method", e);
            if (throwException) {
                throw new RuntimeException(e);
            }
        }
    }
}
